package com.crazymakercircle.reactormodel;

import com.crazymakercircle.Config;
import com.crazymakercircle.util.Dateutil;
import com.crazymakercircle.util.Logger;
import com.crazymakercircle.util.Print;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * create by 尼恩 @ 疯狂创客圈
 **/
public class EchoClient {

    public static void main(String[] args) throws IOException {

        InetSocketAddress address = new InetSocketAddress(Config.SOCKET_SERVER_IP, Config.SOCKET_SERVER_PORT);
        // 1、获取通道（channel）
        SocketChannel socketChannel = SocketChannel.open(address);
        // 2、切换成非阻塞模式
        socketChannel.configureBlocking(false);
        //不断的自旋、等待连接完成，或者做一些其他的事情
        while (!socketChannel.finishConnect()) {

        }
        Print.tcfo("客户端启动成功！");

        //启动接受线程
        new Thread(new Processor(socketChannel)).start();

    }

    static class Processor implements Runnable {
        final Selector selector;
        final SocketChannel channel;

        Processor(SocketChannel channel) throws IOException {
            selector = Selector.open();
            this.channel = channel;
            channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
        }

        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    selector.select();
                    Set<SelectionKey> selected = selector.selectedKeys();
                    Iterator<SelectionKey> it = selected.iterator();
                    while (it.hasNext()) {
                        SelectionKey selectionKey = it.next();
                        if (selectionKey.isWritable()) {
                            try {
                                dealWrite(selectionKey);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        if (selectionKey.isReadable()) {
                            dealRead(selectionKey);
                        }
                    }
                    selected.clear();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        private void dealRead(SelectionKey selectionKey) throws IOException {
            // 若选择键的IO事件是“可读”事件,读取数据
            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int length;
            while ((length = socketChannel.read(byteBuffer)) > 0) {
                byteBuffer.flip();
                Logger.info("server echo:" + new String(byteBuffer.array(), 0, length));
                byteBuffer.clear();
            }
        }

        private void dealWrite(SelectionKey selectionKey) throws IOException, InterruptedException {
            ByteBuffer buffer = ByteBuffer.allocate(Config.SEND_BUFFER_SIZE);
            TimeUnit.SECONDS.sleep(2);
            Print.tcfo("请输入发送内容:");
//            if (scanner.hasNext()) {
            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
            String next = "123";
            buffer.put((Dateutil.getNow() + " >>" + next).getBytes());
            buffer.flip();
            // 操作三：通过DatagramChannel数据报通道发送数据
            socketChannel.write(buffer);
            buffer.clear();
//            }
        }
    }

}
